package services

import (
	"encoding/json"
	"fmt"
	"github.com/jinzhu/gorm"
	"go_motor_catalog/dao"
	"go_motor_catalog/util"
	"strings"
)

const (
	modelListUrl     = "https://www.ducati.com/ww/en/api/accessories/filters"
	DucatiCatalogUrl = "https://www.ducati.com/ww/en/api/bikes/bike-documents?family=FAMILY&model=MODEL&year=YEAR&category=user-manuals"
)

type DucatiOm struct {
}

func NewDucatiOm() *DucatiOm {
	return &DucatiOm{}
}

type DucatiOmRes struct {
	ModelName       string
	ModelYear       string
	CatalogUrl      string
	CatalogShareUrl string
	Desc            string
}

func (d *DucatiOm) GetModelList() []map[string]string {
	res := make([]map[string]string, 0)
	response := util.NewHttpUtil().GetHeadResty(
		modelListUrl,
		"User-Agent",
		"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36",
	)

	body := response.Body()
	var oneLevel map[string]interface{}
	var twoLevel map[string]map[string]interface{}
	err := json.Unmarshal(body, &oneLevel)
	if err != nil {
		fmt.Println("解析一级数据失败->", err)
		return res
	}
	twoLevelBody, err := json.Marshal(oneLevel["families"])
	if err != nil {
		fmt.Println("获取二级数据失败->", err)
		return res
	}
	err = json.Unmarshal(twoLevelBody, &twoLevel)
	if err != nil {
		fmt.Println("解析二级数据失败->", err)
		return res
	}
	for s := range twoLevel {
		v := twoLevel[s]
		modelFirstName := fmt.Sprintf("%s", v["name"])
		familyParam := fmt.Sprintf("%s", v["id"])
		var threeLevel []map[string]interface{}
		threeLevelBody, err := json.Marshal(v["allFamilies"])
		if err != nil {
			fmt.Println("获取三级级数据失败->", err)
			continue
		}
		err = json.Unmarshal(threeLevelBody, &threeLevel)
		if err != nil {
			fmt.Println("解析三级级数据失败->", err)
			continue
		}
		for t := range threeLevel {
			m := threeLevel[t]
			var modelLevel []map[string]interface{}
			modelLevelBody, err := json.Marshal(m["allModels"])
			if err != nil {
				fmt.Println("获取四级级数据失败->", err)
				continue
			}
			err = json.Unmarshal(modelLevelBody, &modelLevel)
			if err != nil {
				fmt.Println("解析四级数据失败->", err)
				continue
			}
			for i := range modelLevel {
				modelLastName := fmt.Sprintf("%s", modelLevel[i]["name"])
				modelParam := fmt.Sprintf("%s", modelLevel[i]["id"])
				var fourLevel []map[string]interface{}
				fourLevelBody, err := json.Marshal(modelLevel[i]["allYears"])
				if err != nil {
					fmt.Println("获取四级数据失败->", err)
					continue
				}
				err = json.Unmarshal(fourLevelBody, &fourLevel)
				if err != nil {
					fmt.Println("解析四级数据失败->", err)
					continue
				}
				for f := range fourLevel {
					yearInfo := fourLevel[f]
					year := fmt.Sprintf("%s", yearInfo["name"])
					yearParam := fmt.Sprintf("%s", yearInfo["id"])
					var modelName string
					if modelFirstName == "Scrambler" {
						modelName = modelFirstName + " " + modelLastName
					} else {
						modelName = modelLastName
					}
					res = append(res, map[string]string{
						"year":        year,
						"modelName":   modelName,
						"familyParam": familyParam,
						"modelParam":  modelParam,
						"yearParam":   yearParam,
					})
				}
			}
		}
	}
	return res
}

func (d *DucatiOm) GetCatalogs(param map[string]string) string {
	url := strings.ReplaceAll(DucatiCatalogUrl, "FAMILY", param["familyParam"])
	url = strings.ReplaceAll(url, "MODEL", param["modelParam"])
	url = strings.ReplaceAll(url, "YEAR", param["yearParam"])
	url = strings.ReplaceAll(url, "|", "%7C")
	url = strings.ReplaceAll(url, " ", "%20")
	response := util.NewHttpUtil().GetHead(
		url,
		"User-Agent",
		"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36",
	)
	var categories map[string]interface{}
	err := json.Unmarshal(response, &categories)
	if err != nil {
		fmt.Println("获取图纸失败->{}->", err, url)
		return ""
	}
	categoriesBody, err := json.Marshal(categories["categories"])
	if err != nil {
		fmt.Println("获取图纸失败->{}->{}", err, url)
		return ""
	}
	var documents []map[string]interface{}
	err = json.Unmarshal(categoriesBody, &documents)
	if err != nil {
		fmt.Println("获取图纸失败->{}->{}", err, url)
		return ""
	}
	if len(documents) == 0 {
		return ""
	}
	documentsBody, err := json.Marshal(documents[0]["documents"])
	if err != nil {
		fmt.Println("获取图纸失败->{}->{}", err, url)
		return ""
	}
	var pdfs []map[string]interface{}
	err = json.Unmarshal(documentsBody, &pdfs)
	if err != nil {
		fmt.Println("获取图纸失败->{}->{}", err, url)
		return ""
	}
	assetBody, err := json.Marshal(pdfs[0]["asset"])
	if err != nil {
		fmt.Println("获取图纸失败->{}->{}", err, url)
		return ""
	}
	var asset map[string]string
	err = json.Unmarshal(assetBody, &asset)
	if err != nil {
		fmt.Println("获取图纸失败->{}->{}", err, url)
		return ""
	}
	res := asset["url"]
	fmt.Println("get catalog -> ", res)
	return res
}

func (d *DucatiOm) CrawData(db *gorm.DB) {
	addList := make([]*DucatiOmRes, 0)
	modelList := d.GetModelList()
	for i := range modelList {
		modelInfo := modelList[i]
		catalogUrl := d.GetCatalogs(modelInfo)
		if catalogUrl != "" {
			addList = append(addList, &DucatiOmRes{
				ModelName:       modelInfo["modelName"],
				ModelYear:       modelInfo["year"],
				CatalogUrl:      catalogUrl,
				CatalogShareUrl: "",
				Desc:            "",
			})
		}
	}
	modelOmDao := dao.NewManualModelOmDao(db)
	catalogOmDao := dao.NewManualCatalogOmDao(db)
	for i := range addList {
		param := addList[i]
		modelParam := &dao.ManualModelOm{
			ModelName: param.ModelName,
			ModelYear: param.ModelYear,
			BrandId:   10,
		}
		catalogParam := &dao.ManualCatalogOm{
			CatalogUrl:  param.CatalogUrl,
			CatalogDesc: "",
		}
		modelId := modelOmDao.CreateManualModelOm(modelParam)
		catalogParam.ModelId = modelId
		catalogOmDao.CreateManualCatalogOm(catalogParam)
		fmt.Println(param.ModelName, "-", param.ModelYear, "-successfull")
	}
	fmt.Print("all successfull")
}
